//
//  YSAlertAction.m
//  YSAlertActionExample
//
//  Created by Kyson on 2018/5/7.
//  Copyright © 2018年 YangShen. All rights reserved.
//

#import "YSAlertAction.h"
#import <objc/runtime.h>

//#pragma clang diagnostic push
// 不写push pop 整个类都取消这个警告
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
//写在这个中间的代码,都不会被编译器提示-Wincompatible-pointer-types类型的警告
//#pragma clang diagnostic pop

#pragma mark - Category
@interface UIWindow (YSAlertAction)
//获取当前显示
- (UIViewController*)currentTopViewController;
@end

@implementation UIWindow (YSAlertAction)

- (UIViewController*)topRootController {
    UIViewController *topController = [self rootViewController];
    
    //  Getting topMost ViewController
    while ([topController presentedViewController])    topController = [topController presentedViewController];
    
    //  Returning topMost ViewController
    return topController;
}

- (UIViewController*)currentTopViewController {
    UIViewController *currentTopViewController = [self topRootController];
    
    if ([currentTopViewController isKindOfClass:[UITabBarController class]]
        && ((UITabBarController*)currentTopViewController).selectedViewController != nil ) {
        currentTopViewController = ((UITabBarController*)currentTopViewController).selectedViewController;
    }
    
    while ([currentTopViewController isKindOfClass:[UINavigationController class]]
           && [(UINavigationController*)currentTopViewController topViewController]) {
        currentTopViewController = [(UINavigationController*)currentTopViewController topViewController];
    }
    
    return currentTopViewController;
}

@end

static char alertKey;
@interface UIAlertView (YSAlertAction)

// 用Block的方式回调，这时候会默认用self作为Delegate
- (void)showWithBlock:(void(^)(NSInteger buttonIndex)) block;

@end

@implementation UIAlertView (YSAlertAction)

- (void(^)(NSInteger buttonIndex))block {
    return objc_getAssociatedObject(self, &alertKey);;
}

- (void)setBlock:(void(^)(NSInteger buttonIndex))block {
    if (block) {
        objc_removeAssociatedObjects(self);
        objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_COPY);
    }
}


- (void)showWithBlock:(void(^)(NSInteger buttonIndex))block {
    self.block = block;
    self.delegate = self;
    
    [self show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (self.block) {
        self.block(buttonIndex);
    }
    
    objc_removeAssociatedObjects(self); // 断开所有关联
}

@end

@interface UIAlertController (supportedInterfaceOrientations)

@end

@implementation UIAlertController (supportedInterfaceOrientations)
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations; {
    return UIInterfaceOrientationMaskPortrait;
}
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
#endif
@end

static char actionSheetkey;
@interface UIActionSheet (YSAlertAction) <UIActionSheetDelegate>

- (void)showInView:(UIView *)view block:(void(^)(NSInteger idx,NSString* buttonTitle))block;

@end

#pragma mark - UIActionSheet
@implementation UIActionSheet (YSAlertAction)

- (void(^)(NSInteger idx,NSString* buttonTitle))block {
    return objc_getAssociatedObject(self, &actionSheetkey);;
}

- (void)setBlock:(void(^)(NSInteger idx,NSString* buttonTitle))block {
    if (block) {
        objc_setAssociatedObject(self, &actionSheetkey, block, OBJC_ASSOCIATION_COPY);
    }
}

- (void)showInView:(UIView *)view block:(void(^)(NSInteger idx,NSString* buttonTitle))block {
    self.block = block;
    
    self.delegate = self;
    [self showInView:view];
}


// Called when a button is clicked. The view will be automatically dismissed after this call returns
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (self.block) {
        self.block(buttonIndex,[self buttonTitleAtIndex:buttonIndex]);
    }
    
    objc_removeAssociatedObjects(self);
}

// Called when we cancel a view (eg. the user clicks the Home button). This is not called when the user clicks the cancel button.
// If not defined in the delegate, we simulate a click in the cancel button
- (void)actionSheetCancel:(UIActionSheet *)actionSheet {
    objc_removeAssociatedObjects(self);
}

@end

@implementation YSAlertAction

+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle buttonIndexBlock:(YSAlertClickBlock)buttonIndexBlock otherButtonTitles:(NSString *)otherButtonTitles, ... {
    
    if ( [self isIosVersion8AndAfter]) {
        // UIAlertController
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *action = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            if (buttonIndexBlock) {
                buttonIndexBlock(0);
            }
        }];
        [alertController addAction:action];
        
        if (otherButtonTitles) {
            NSInteger i = 1;
            va_list args;//定义一个指向个数可变的参数列表指针
            va_start(args, otherButtonTitles);//得到第一个可变参数地址
            for (NSString *arg = otherButtonTitles; arg != nil; arg = va_arg(args, NSString *)) {
                UIAlertActionStyle style = UIAlertActionStyleDefault;
                UIAlertAction *action = [UIAlertAction actionWithTitle:arg style:style handler:^(UIAlertAction *action) {
                    if (buttonIndexBlock) {
                        buttonIndexBlock(i);
                    }
                }];
                [alertController addAction:action];
                
                i++;
            }
            va_end(args);//置空指针
        }
        
        [[self getTopViewController] presentViewController:alertController animated:YES completion:nil];
        return;
    }
    
    // UIAlertView
    UIAlertView* alertView = [[UIAlertView alloc]initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil, nil];
    
    if (otherButtonTitles) {
        va_list args;//定义一个指向个数可变的参数列表指针
        va_start(args, otherButtonTitles);//得到第一个可变参数地址
        for (NSString *arg = otherButtonTitles; arg != nil; arg = va_arg(args, NSString *)) {
            [alertView addButtonWithTitle:arg];
        }
        va_end(args);//置空指针
    }
    
    [alertView showWithBlock:^(NSInteger buttonIdx) {
        if (buttonIndexBlock) {
            buttonIndexBlock(buttonIdx);
        }
    }];
}

+ (void)showAlertSheetWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle buttonIndexBlock:(YSAlertClickBlock)buttonIndexBlock otherButtonTitles:(NSString *)otherButtonTitles, ... {
    
    if ( [self isIosVersion8AndAfter]) {
        UIAlertController* alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];
        
        // Create the actions.
        UIAlertAction *action = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            if (buttonIndexBlock) {
                buttonIndexBlock(0);
            }
        }];
        [alertController addAction:action];
        
        if (otherButtonTitles) {
            NSInteger i = 1;
            va_list args;//定义一个指向个数可变的参数列表指针
            va_start(args, otherButtonTitles);//得到第一个可变参数地址
            for (NSString *arg = otherButtonTitles; arg != nil; arg = va_arg(args, NSString *)) {
                UIAlertActionStyle style = UIAlertActionStyleDefault;
                UIAlertAction *action = [UIAlertAction actionWithTitle:arg style:style handler:^(UIAlertAction *action) {
                    if (buttonIndexBlock) {
                        buttonIndexBlock(i);
                    }
                }];
                [alertController addAction:action];
                
                i++;
            }
            va_end(args);//置空指针
        }
        [[self getTopViewController] presentViewController:alertController animated:YES completion:nil];
        return;
    }
    
    UIView *view = [self getTopViewController].view;
    UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title delegate:nil cancelButtonTitle:cancelButtonTitle destructiveButtonTitle:nil otherButtonTitles:otherButtonTitles, nil];
    [sheet showInView:view block:^(NSInteger buttonIdx,NSString* buttonTitle) {
        if (buttonIndexBlock) {
            buttonIndexBlock(buttonIdx);
        }
    }];
    
}

#pragma mark - Helper
+ (BOOL)isIosVersion8AndAfter {
    return [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ;
}

+ (UIViewController*)getTopViewController {
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    return window.currentTopViewController;
}

@end
